From 064a4d414b4768dff82ae5bbd9e703b4442c214a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 8 Dec 2005 15:18:13 +0100 Subject: [PATCH] Fixed a get/put_page mismatch for guest L2 pages. Sometimes, when you destroy an OS when it is in real mode, there is an extra put_page in domain_relinquish_resource. This causes the page be freed with non-zero type count. With ASSERT enabled, hypervisor will crash; with debug=n, on some machines, the system will hang in alloc_domheap_pages, due to type_info being a union with cpumask and not equal to 0. Signed-off-by: Xiaofeng Ling --- xen/arch/x86/vmx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index e8e1c9f1e0..eb1252ff1c 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -905,7 +905,7 @@ vmx_world_save(struct vcpu *v, struct vmx_assist_context *c) int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) { - unsigned long mfn, old_cr4; + unsigned long mfn, old_cr4, old_base_mfn; int error = 0; error |= __vmwrite(GUEST_RIP, c->eip); @@ -945,7 +945,12 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) return 0; } mfn = get_mfn_from_pfn(c->cr3 >> PAGE_SHIFT); + if(!get_page(pfn_to_page(mfn), v->domain)) + return 0; + old_base_mfn = pagetable_get_pfn(v->arch.guest_table); v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT); + if (old_base_mfn) + put_page(pfn_to_page(old_base_mfn)); update_pagetables(v); /* * arch.shadow_table should now hold the next CR3 for shadow @@ -1174,9 +1179,11 @@ static int vmx_set_cr0(unsigned long value) } if(!((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled) - if(v->arch.arch_vmx.cpu_cr3) + if(v->arch.arch_vmx.cpu_cr3){ put_page(pfn_to_page(get_mfn_from_pfn( v->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT))); + v->arch.guest_table = mk_pagetable(0); + } /* * VMX does not implement real-mode virtualization. We emulate -- 2.30.2